use base64::prelude::*;
use zuc::Zuc;

mod zuc;

pub fn encryption(input: String) -> String {
    let key = [0; 16];
    let iv = [1; 16];
    let mut zuc = Zuc::new(key, iv);

    // padding the input data with PKCS #7
    let len = input.as_bytes().len();
    let pad = (4 - len % 4) as u8;
    let mut data = input.as_bytes().iter();
    let mut ans = Vec::<u8>::new();
    while let Some(a) = data.next() {
        // gather 32 bits as one encrypt block
        let mut v = *a as u32;
        for _ in 0..3 {
            v = (v << 8) | *data.next().unwrap_or(&pad) as u32;
        }
        // encrypt (xor with ZUC's output)
        v ^= zuc.work();
        ans.append(&mut Vec::from(v.to_be_bytes()));
    }
    if pad == 4 {
        ans.append(&mut Vec::from((zuc.work() ^ 0x04040404).to_be_bytes()));
    }
    // output with base64 format
    BASE64_STANDARD.encode(ans)
}
